using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Workflow.ComponentModel.Compiler;
using OpenComposite.Base.Designer;
using OpenComposite.EII.Designer.SCA;
using OpenComposite.EII.Designer.Workflow;
using OpenComposite.Repository.Properties;
using OpenComposite.EII.Repository;
using WeifenLuo.WinFormsUI.Docking;

namespace OpenComposite.EII.Designer.BUSView
{
	public class BUSViewController : DesignController
	{
		#region Initialization

		public BUSViewController(RepositorySurfaceManager surfaceManager)
			: base(surfaceManager)
		{
			_serviceProvider = surfaceManager;
			SimpleMode = true;
			_isBusView = true;
		}

		#endregion

		#region Public Members

		#region Properties
		public IServiceProvider WorkflowServiceProvider
		{
			get { return _serviceProvider; }
			set { _serviceProvider = value; }
		}
		public Repository.Workflow Workflow
		{
			get { return _diagramItem as Repository.Workflow; }
			set { _diagramItem = value; }
		}
		public Type WorkflowClassType
		{
			get
			{
				TypeProvider typeProvider = (TypeProvider)this.GetService(typeof(ITypeProvider));
				return typeProvider.GetType(this.Workflow.ExtendedProperties.FullName);
			}
		}

		public override object View
		{
			get
			{
				return _ucView;
			}
		}
		#endregion

		#region Methods
		public override void Show(WeifenLuo.WinFormsUI.Docking.DockPanel dockPanel)
		{
			base.Show(dockPanel);
			this.DesignerDockContent.Icon = Resources.ico_bus;
		}
		public override bool Load(RepositoryItemBaseEx item, int repositoryId, int domainId)
		{
			this.Workflow = item as Repository.Workflow;
			if ( this.Workflow == null )
				throw new ArgumentException("Item is not an Repository Workflow.", "item");

			LoadDiagram();
			initSubscriptionList();

			return true;
		}
		public override bool Load(ItemType diagramType, RepositoryItemBaseEx item, int repositoryId, int domainId)
		{
			this.Workflow = item as Repository.Workflow;
			if ( this.Workflow == null )
				throw new ArgumentException("Item is not an Repository Workflow.", "item");

			LoadDiagram();
			initSubscriptionList();

			return true;
		}
		public override bool Save()
		{
			if ( this.Workflow == null )
				return false;

			try {

				List<DesignerControl> oldHierarchy = null;
				bool saved = false;
				// save diagram main item
				//if ( this.Designer.DesignerView.MainControl != null &&
				//     this.Designer.DesignerView.MainControl is IRepositoryItemSymbol ) {
				//    RepositoryItemBaseEx mainitem =
				//        ( (IRepositoryItemSymbol)this.Designer.DesignerView.MainControl )
				//            .RepositoryItem as RepositoryItemBaseEx;
				//    if ( mainitem != null ) {
				//        oldHierarchy = this.Designer.DesignerView.LoadDiagramFromXmlAndGetTopControlsHierarchyOnly(
				//            mainitem.Diagram, this.Designer.DesignerView.Types);
				//        mainitem.Diagram = this.GetXmlDocument();
				//        saved = ( (IRepositoryItemSymbol)this.Designer.DesignerView.MainControl ).Save(_idRepository, _idDomain);
				//    }
				//}
				if ( !saved && this.Workflow != null ) {
					oldHierarchy = this.DesignerView.LoadDiagramFromXmlAndGetTopControlsHierarchyOnly(
						this.Workflow.BUSDiagram, this.DesignerView.Types);
					this.Workflow.BUSDiagram = this.GetXmlDocument();
					this.Workflow.Save();
				}
				if ( _isBusView ) {
					// save other diagram items
					SaveItems(oldHierarchy);
				}
				OnSaved();
			} catch ( Exception ex ) {
				MessageBox.Show(ex.Message, this.TabText, MessageBoxButtons.OK, MessageBoxIcon.Error);
				return false;
			}
			if ( this.DesignerDockContent != null ) {
				this.DesignerDockContent.Activate();
			}
			return true;
		}

		public override Route CreateNewRoute(DesignerControl start, DesignerControl end)
		{
			if ( start is BUSActivitySymbol && end is BUSSymbol ) {
				// publish
				return new BUSPublishRoute();
			} else if ( start is BUSSymbol && end is BUSActivitySymbol ) {
				// subscribe
				return new BUSSubscribeRoute();
			} else {
				return base.CreateNewRoute(start, end);
			}
		}

		public override object GetView(ViewTechnology technology)
		{
			if ( technology != ViewTechnology.Default ) {
				throw new ArgumentException("Not a supported view technology", "technology");
			}
			if ( _ucView == null ) {
				InitView();
			}
			designerView.Types = DesignerControlTypes.ToArray();

			if ( this.DesignerDockContent != null ) {
				this.DesignerDockContent.SuspendLayout();
			} else {
				this._ucView.SuspendLayout();
			}
			try {
				_isBusView = false;
				_ucSubscriptionList.BringToFront();
				_ucSubscriptionList.UpdateList();
				this.DesignerView.Visible = _isBusView;
				_ucSubscriptionList.Visible = !_isBusView;
				setSwitchButtonText();
			} catch ( Exception ex ) {
				System.Diagnostics.Debug.WriteLine("[BUSViewController] " + ex.Message);
			}
			if ( this.DesignerDockContent != null ) {
				this.DesignerDockContent.ResumeLayout(true);
			} else {
				this._ucView.ResumeLayout(true);
			}

			return _ucView;
		}

		public void RefreshSwitchButtons()
		{
			setModeButtonText();
			setSwitchButtonText();
		}

		public void Update()
		{
			if ( _isBusView ) {
				if ( this.DesignerDockContent != null ) {
					this.DesignerDockContent.BringToFront();
				} else {
					this._ucView.BringToFront();
				}
				this.LoadItems();
			} else {
				this.Save();
				_ucSubscriptionList.BringToFront();
				_ucSubscriptionList.UpdateList();
			}
		}
		#endregion

		#endregion

		#region Protected Members

		#region Methods

		// override
		protected override void LoadDiagram()
		{
			RepositoryService repSvc = (RepositoryService)this.GetService(typeof(RepositoryService));
			if ( repSvc == null )
				throw new NullReferenceException("RepositoryService not available.");

			BUSSymbol bus = null;
			DesignerControl dc = null;
			if ( this.Workflow == null )
				throw new NullReferenceException("BUSViewController.Workflow is null.");

			if ( this.Workflow.BUSDiagram == null ) {
				Point ptViewPos = this.DesignerView.ViewPosition;
				this.DesignerView.ViewPosition = new Point(0, ptViewPos.Y);
				this.DesignerView.MainPanel.Left = 0;
				// create new designer control
				dc = repSvc.CreateDesignerControl(ItemType.BUS, false);
				if ( dc != null ) {
					Point loc = new Point(20, ptViewPos.Y + dc.Height + 100);
					this.DesignerView.AddDesignerControl(dc);
					dc.Location = loc;
					// set designer main control
					this.DesignerView.MainControl = dc;
					bus = dc as BUSSymbol;
				}
			} else {
				// load diagram
				this.DesignerView.BeginUpdate();
				this.DesignerView.LoadDiagramFromXml(this.Workflow.BUSDiagram, DesignerControlTypes.ToArray());
				this.DesignerView.EndUpdate();
				foreach ( DesignerControl dctrl in this.DesignerView.DesignerControls ) {
					if ( dctrl is BUSSymbol ) {
						bus = (BUSSymbol)dctrl;
						break;
					}
				}
			}
			if ( bus != null ) {
				//if ( this.Workflow.OutputBusinessObject != null )
				//    bus.OutputBusinessObject = this.Workflow.OutputBusinessObject;
			}

			LoadItems();
		}
		protected override void LoadItems()
		{
			List<BUSActivitySymbol> activities = new List<BUSActivitySymbol>();
			foreach ( DesignerControl dc in this.DesignerView.DesignerControls ) {
				if ( dc is BUSActivitySymbol )
					activities.Add((BUSActivitySymbol)dc);
			}
			foreach ( BUSActivitySymbol busact in activities ) {
				busact.Load(_idRepository, _idDomain);
			}
		}

		protected override void SaveItems(List<DesignerControl> oldHierarchy)
		{
			foreach ( DesignerControl dc in this.DesignerView.DesignerControls.ControlsWithoutRoutes ) {
				if ( dc is BUSActivitySymbol )
					RecursiveSaveItems(dc, null);
			}
		}
		protected override void RecursiveSaveItems(DesignerControl dcCurrent, IRepositoryItem itemParent)
		{
			IRepositoryItemSymbol ris = dcCurrent as IRepositoryItemSymbol;
			if ( ris != null ) {
				ris.Save(_idRepository, _idDomain);
			}
		}

		protected override void OnClosing(FormClosingEventArgs e)
		{
			base.OnClosing(e);
			if ( !_isBusView ) {
				this.LoadItems();
			}
		}
		protected override void OnClosed()
		{
			base.OnClosed();
		}

		protected override void InitDockContent(Control view)
		{
			base.InitDockContent(view);

			try {
				this.DesignerDockContent.SuspendLayout();
				_isBusView = true;

				this.DesignerDockContent.ToolStrip.Items.Add(new ToolStripSeparator());
				this.DesignerDockContent.ToolStrip.Items.Add(
					"Rule Vocabulary Assignment...",
					Resources.png_brule,
					new EventHandler(this.VocabularyResolve_Click));
				//
				// tsbtnSwitchView
				//
				this.tsbtnSwitchView = new ToolStripButton();
				this.tsbtnSwitchView.Click += new EventHandler(tsbtnSwitchView_Click);

				//
				// tsbtnSimpleAdvanced
				//
				this.tsbtnSimpleAdvanced = new ToolStripButton();
				this.tsbtnSimpleAdvanced.Click += new EventHandler(tsbtnSimpleAdvanced_Click);

				this.DesignerDockContent.ToolStrip.Items.Add(new ToolStripSeparator());
				this.DesignerDockContent.ToolStrip.Items.Add(this.tsbtnSwitchView);
				this.DesignerDockContent.ToolStrip.Items.Add(this.tsbtnSimpleAdvanced);


				setSwitchButtonText();

				this.DesignerDockContent.ResumeLayout(true);
			} catch { }
		}
		protected override void InitView()
		{
			base.InitView();

			_ucView = new UserControl();
			_ucView.SuspendLayout();

			// add toolstrip
			ToolStrip ts = new ToolStrip();
			ts.Items.Add(
				"Rule Vocabulary Assignment...",
				Resources.png_brule,
				new EventHandler(this.VocabularyResolve_Click));
			//
			// tsbtnSwitchView
			//
			this.tsbtnSwitchView = new ToolStripButton();
			this.tsbtnSwitchView.Click += new EventHandler(tsbtnSwitchView_Click);

			//
			// tsbtnSimpleAdvanced
			//
			this.tsbtnSimpleAdvanced = new ToolStripButton();
			this.tsbtnSimpleAdvanced.Click += new EventHandler(tsbtnSimpleAdvanced_Click);

			ts.Items.Add(new ToolStripSeparator());
			ts.Items.Add(this.tsbtnSwitchView);
			ts.Items.Add(this.tsbtnSimpleAdvanced);

			setSwitchButtonText();
			setModeButtonText();

			this.DesignerView.Dock = DockStyle.Fill;

			_ucView.Controls.Add(this.DesignerView);
			_ucView.Controls.Add(ts);

			_ucView.ResumeLayout(true);
		}

		#endregion

		#endregion

		#region Private Members

		#region Variables
		private ToolStripButton tsbtnSwitchView;
		private ToolStripButton tsbtnSimpleAdvanced;
		private UCSubscriptionList _ucSubscriptionList;
		private bool _isBusView;
		private UserControl _ucView;
		private IServiceProvider _serviceProvider;
		private WorkflowController Controller
		{
			get { return _serviceProvider as WorkflowController; }
		}
		#endregion

		#region Methods
		private void initSubscriptionList()
		{
			if ( _ucSubscriptionList != null ) {
				return;
			}
			if ( this.DesignerDockContent != null ) {
				this.DesignerDockContent.SuspendLayout();
				//
				// _ucSubscriptionList
				//
				_ucSubscriptionList = new UCSubscriptionList(this.WorkflowServiceProvider as Workflow.WorkflowController);
				_ucSubscriptionList.Visible = !_isBusView;
				_ucSubscriptionList.Dock = DockStyle.Fill;

				this.DesignerDockContent.Controls.Add(_ucSubscriptionList);

				this.DesignerDockContent.ResumeLayout(true);
			} else if ( _ucView != null ) {
				this._ucView.SuspendLayout();
				//
				// _ucSubscriptionList
				//
				_ucSubscriptionList = new UCSubscriptionList(this.WorkflowServiceProvider as Workflow.WorkflowController);
				_ucSubscriptionList.Visible = !_isBusView;
				_ucSubscriptionList.Dock = DockStyle.Fill;
				_ucSubscriptionList.SetSimpleMode(true);

				this._ucView.Controls.Add(_ucSubscriptionList);

				this._ucView.ResumeLayout();
			}
		}
		private void switchView()
		{
			if ( this.DesignerDockContent != null ) {
				this.DesignerDockContent.SuspendLayout();
			} else {
				this._ucView.SuspendLayout();
			}
			try {
				using ( new OpenComposite.Base.WaitMouse() ) {
					// save current view
					this.Save();
					// change current view flag
					_isBusView = !_isBusView;

					if ( _isBusView ) {
						// initialize bus view
						if ( this.DesignerDockContent != null ) {
							this.DesignerDockContent.BringToFront();
						} else {
							this._ucView.BringToFront();
						}
						this.LoadItems();
					} else {
						// initialize list view
						_ucSubscriptionList.BringToFront();
						_ucSubscriptionList.UpdateList();
					}
					// display current view
					this.DesignerView.Visible = _isBusView;
					_ucSubscriptionList.Visible = !_isBusView;
				}
			} catch ( Exception ex ) {
				MessageBox.Show(ex.Message, this.RepositoryItem.Name, MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
			// switch button text
			setSwitchButtonText();
			if ( this.DesignerDockContent != null ) {
				this.DesignerDockContent.ResumeLayout(true);
			} else {
				this._ucView.ResumeLayout(true);
			}
		}
		private void switchMode()
		{
			SimpleMode = !SimpleMode;
			setModeButtonText();
			this.DesignerView.Invalidate();
			if ( _isBusView ) {
				foreach ( DesignerControl dctrl in this.DesignerView.DesignerControls.ToArray() ) {
					BUSDocumentSymbol symbol = dctrl as BUSDocumentSymbol;
					if ( symbol == null ) continue; ;
					symbol.OnLayout();
				}
			} else {
				_ucSubscriptionList.SetSimpleMode(this.SimpleMode);
			}
		}
		internal bool SimpleMode { get; private set; }
		private void setSwitchButtonText()
		{
			if ( _isBusView ) {
				this.tsbtnSwitchView.Text = "Switch to List View";
				this.tsbtnSwitchView.Image = Resources.png_list;
			} else {
				this.tsbtnSwitchView.Text = "Switch to BUS View";
				this.tsbtnSwitchView.Image = Resources.png_bus;
				//_ucSubscriptionList.SetSimpleMode(this.SimpleMode);
			}

		}
		private void setModeButtonText()
		{
			if ( SimpleMode ) {
				this.tsbtnSimpleAdvanced.Text = "Show Variable Names";
				this.tsbtnSimpleAdvanced.Image = Resources.png_field;
			} else {
				this.tsbtnSimpleAdvanced.Text = "Show Business Object Names";
				this.tsbtnSimpleAdvanced.Image = Resources.bobject;
			}
		}
		#endregion

		#region Event Handlers
		FormVocabularyResolve _formVocabResolve = null;
		private void VocabularyResolve_Click(object sender, EventArgs e)
		{
			Application.DoEvents();
			DockPanel dp = null;
			if ( this.designerDockContent != null ) {
				dp = designerDockContent.DockPanel;
			} else {
				dp = _surfaceManager.GetService(typeof(DockPanel)) as DockPanel;
			}
			if ( _formVocabResolve == null || _formVocabResolve.IsDisposed ) {
				_formVocabResolve = new FormVocabularyResolve(this.Workflow, this);
				_formVocabResolve.FormClosed += new FormClosedEventHandler(frm_FormClosed);
			}
			if ( dp != null ) {
				Point loc = new Point(dp.Left + dp.Width / 2 - _formVocabResolve.Width / 2, dp.Top + dp.Height / 2 - _formVocabResolve.Height / 2);
				////_formVocabResolve.Location = dp.PointToScreen(loc);
				_formVocabResolve.Show(dp, new Rectangle(dp.PointToScreen(loc), new Size(500, 350)));
				//_formVocabResolve.Show(dp);
				//_formVocabResolve.Location = dp.PointToScreen(loc);
				//if ( Controller != null ) Controller.IsChanged = true;
			} else {
				if ( _formVocabResolve.ShowDialog() == DialogResult.OK ) {
					if ( Controller != null ) Controller.IsChanged = true;
				}
			}
		}

		private void frm_FormClosed(object sender, FormClosedEventArgs e)
		{
			FormVocabularyResolve frm = sender as FormVocabularyResolve;
			if ( frm != null ) {
				frm.FormClosed -= new FormClosedEventHandler(frm_FormClosed);
				frm.DockPanel.TopLevelControl.BringToFront();
			}
		}
		private void tsbtnSwitchView_Click(object sender, EventArgs e)
		{
			switchView();
		}

		void tsbtnSimpleAdvanced_Click(object sender, EventArgs e)
		{
			switchMode();
		}
		#endregion

		#endregion
	}
}
